{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 第7章 包、模块、类"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7-5 python工程的组织结构：包、模块和类\n",
    "\n",
    "+ Python组织结构的意义：在相对复杂的项目下，便于管理，便于维护，便于复用\n",
    "+ 组织结构：包（可以理解为文件夹）> 模块（.py文件）> 类（class：包括函数、变量, 函数变量算作类里的具体组成部分，类的特性）\n",
    "  > 一个py文件时一个模块，一个模块里可以有多个类\n",
    "+ 之前学到的都是直接在模块下写函数、变量，最好还是把函数变量组织成“类”\n",
    "\n",
    "[python工程的组织结构图](https://img.mukewang.com/szimg/5a86998b000155a919201080.jpg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7-6 python包与模块的名字\n",
    "\n",
    "+ 路径叫做命名空间\n",
    "+ 包的名字就是文件夹的名字，模块的名字就是文件的名字\n",
    "+ 区分不同包的同名模块 比如都叫c4模块，但是在不同的包下：seven.c4 six.c4\n",
    "+ `包名.模块名` 组成一个路径\n",
    "+ `__init__.py` 让普通文件夹变成一个包，用来标注一个包, init模块名字就是包名 seven"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7-7 import导入模块\n",
    "\n",
    "模块导入import  #import不能直接导入变量\n",
    "导入模块语法：\n",
    "+ 一.`import 模块名`  \n",
    "  注意：\n",
    "  + (1).使用模块前请先导入后使用\n",
    "  + (2).使用导入模块中的变量或函数的格式：模块名.变量或函数。\n",
    "+ 二.如果结构不同层级，要用命名空间解决。\n",
    "  ```python\n",
    "  import t.c7\n",
    "  print(t.c7.a)\n",
    "  ```\n",
    "+ 三.`import 模块名 as 名称`\n",
    "  此语法可以解决命名空间过长问题。\n",
    "  如：\n",
    "  ```python\n",
    "  import t.c7 as m\n",
    "  print(m.a)\n",
    "  ```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7-8 from import 导入变量\n",
    "\n",
    "+ (1)导入变量：`from module import a ,def`\n",
    "\n",
    "  调用a的时候不需要命名空间(module.a)\n",
    "\n",
    "+ (2)`*`表示导入文件的所有变量，函数\n",
    "\n",
    "  可以控制能被引用的函数和变量,利用 __all__（模块的内置变量、内置属性）\n",
    "  在模块里定义__all__: \n",
    "  ```python\n",
    "  __all__ = ['a','c'] \n",
    "  ```\n",
    "  这样在from 模块 import * 时,别的模块就只能导入a、c变量(可以强行from 模块 import b  强行导入)\n",
    "\n",
    "+ from import用法比较灵活,可以从包引入模块"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7-9 `__init__.py`的用法\n",
    "\n",
    "+ 当包或该包下的模块,变量..被导入时，该文件自动执行。可以用来做包和模块的初始化。\n",
    "+ 可以在`__init___.py`文件中定义`''__all__''`变量来定义该包下哪些模块可以被其它模块引用(from 包 import *)。\n",
    "+ 可以利用`__init__.py`文件做批量导入\n",
    "  在子包的 `__init__.py`文件里导入需要的模块, 然后在上一级 import 子包名 进行模块的批量导入  注意 ::引用的时候注意命名空间 子包名.def"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7-10 包与模块的几个常见错误\n",
    "\n",
    "+ 1.包和模块不会被重复导入\n",
    "+ 2.避免循环导入，不管是直接循环还是间接循环。\n",
    "  + 1）直接循环：p1.py中导入p2.py的变量，同时p2.py中又导入p1.py的变量。\n",
    "  + 2）间接循环：p1.py中导入p2.py的变量，p2.py中导入p3.py的变量，p3.py中导入p4.py的变量，p4.py中导入p1.py的变量，形成一个闭环。\n",
    "  + 解决方法：打开循环，取消最后一个文件的import语句或变为注释"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7-11 模块的内置变量\n",
    "\n",
    "+ 1.`dir()`函数：返回当前模块的所有变量\n",
    "+ 2.`__name__`:模块名称\n",
    "+ 3.`__package__`:包名\n",
    "+ 4.`__doc__`:模块的注释\n",
    "+ 5.`__file__`:当前文件的物理路径"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['In',\n",
       " 'Out',\n",
       " '_',\n",
       " '__',\n",
       " '___',\n",
       " '__builtin__',\n",
       " '__builtins__',\n",
       " '__doc__',\n",
       " '__loader__',\n",
       " '__name__',\n",
       " '__package__',\n",
       " '__spec__',\n",
       " '_dh',\n",
       " '_i',\n",
       " '_i1',\n",
       " '_i2',\n",
       " '_ih',\n",
       " '_ii',\n",
       " '_iii',\n",
       " '_oh',\n",
       " 'exit',\n",
       " 'get_ipython',\n",
       " 'quit']"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dir()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'__main__'"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "__name__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "__package__"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Automatically created module for IPython interactive environment'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "__doc__"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7-12 入口文件\n",
    "\n",
    "入口文件的特点：\n",
    "+ 1、变量`__name__`打印的值会被强制更改为`__main__`\n",
    "+ 2、如果一个.py文件被当作入口文件，则它为顶级文件，不会再有包；\n",
    "+ 3、file 的值和执行python命令所在目录有关，是不确定的值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7-13 `__name__`的经典应用\n",
    "\n",
    "+ 1.dir（）函数括号内如果什么都不写，则输出的是当前模块里所有的变量。当需要查看某个函数或类里的变量时，可以使用dir()函数\n",
    "+ 2.python中的普通模块必须有一个包，当想要把一个可执行文件当作一个普通模块运行时，可以使用-m参数，如：python -m 命名空间(包).模块名\n",
    "+ 3.`if __name__ == '__main__' :` 意思是：make a script both importable and executable(让这个脚本既可以作为一个普通的模块被导入到其他模块中，也可以作为可执行模块）\n",
    "  作用：判断当前模块是否为入口文件"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7-14~7-15 相对导入和绝对导入\n",
    "\n",
    "+ 1、顶级包的位置由入口文件 main.py 决定，及与入口文件同级别的文件夹（包）,可以用`__package__`来查看，结果的.最前面的内容就是顶级包\n",
    "+ 2、绝对导入（绝对路径）：必须从顶级包一直往下到啊模块；\n",
    "+ 3、相对路径：要使用 from ... import...\n",
    "+ 4、一个点表示当前目录，两个点表示上一级目录，类推；\n",
    "+ 5、**入口文件只可以使用绝对路径导入，不可以使用相对路径导入**  \n",
    "  相对路径能够找到对应的模块是根据内置模块变量`__name__`来定位，入口文件被执行后`__name__`就不是所谓的模块名而是将被python改成`__main__`  , `__main__` 模块是不存在的，所以不可以使用相对路径导入。如果想用相对导入也是可以的，用模块的形式，返回模块的上一级。这个好像是python升级python3模块前的.要去掉的原因"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
